#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "rngs.h"
#include <stdlib.h>
#include <time.h> 


int getNumPlayers(int maxPlayers);
int getNumCurseCards(int maxCurseCards);
int setCurrentPlayersHand(struct gameState* gameState, int currentPlayer);
int* initalizePlayerDecks(struct gameState* gameState);
void testSeaHag();
void displayTestConditions(int numCurseCards, int numPlayers, struct gameState* gameState, int currentPlayer);
int getExpectedCurseCardCount(struct gameState* gameState, int currentPlayer, int numCurseCards);

int main(int argc, char *argv[]) {
        srand(time(NULL));
        int numTestRuns = 10000;
      
        printf("Attempting %d test runs. Of the Sea_hag card \n", numTestRuns);

        int i = 0;
        for (; i < numTestRuns; i++) {
                printf("\nRun # %d \n", i);
                testSeaHag();
        }
        
        return 0;
}

int getNumPlayers(int maxPlayers) {
        int minPlayers = 2;
        int numPlayers = rand() % (maxPlayers + 1 - minPlayers) + minPlayers; 
        return numPlayers;
}

int getNumCurseCards(int maxCurseCards) {
        return rand() % (maxCurseCards + 1);
}

void displayTestConditions(int numCurseCards, int numPlayers, struct gameState* gameState, int currentPlayer) {
        printf("Test initialized with %d players and %d curse cards \n", numPlayers, numCurseCards);
        printf("Player %d is the current player \n", currentPlayer);
        int playerNumber = 0;
        for (; playerNumber < gameState->numPlayers; playerNumber++) {
                if (playerNumber != currentPlayer) {
                        printf("Player %d started with %d cards in their deck\n", playerNumber, gameState->deckCount[playerNumber]);
                }
        }
        printf("\n");

}

void testSeaHag() {
        int maxCurseCards = 30;
        int numPlayers = getNumPlayers(MAX_PLAYERS); //MAX_PLAYERS is defined in dominion.h and is currently set to 4
        int numCurseCards = getNumCurseCards(maxCurseCards);
        int kingdomCards[10] = {adventurer, council_room, feast, gardens, mine, remodel, smithy, village, baron, great_hall};  
        struct gameState* gameState = newGame();
        int randomSeed = 100;
        if (initializeGame(numPlayers, kingdomCards, randomSeed, gameState) != 0){
                printf("Error initalizing game. \n");
                printf("Number of players = %d \n", numPlayers);
                return;
        }

        int* initalDeckCount = initalizePlayerDecks(gameState);
        gameState->supplyCount[curse] = numCurseCards;
        
        int currentPlayer = 0;
        int handPos = setCurrentPlayersHand(gameState, currentPlayer);

        
        gameState->whoseTurn = currentPlayer;

        displayTestConditions(numCurseCards, numPlayers, gameState, currentPlayer);
        
        int choice1 = 0;
        int choice2 = 0;
        int choice3 = 0;
        int bonus = 0;

        cardEffect(sea_hag, choice1, choice2, choice3, gameState, handPos, &bonus);


        if (numCurseCards < numPlayers - 1) { //-1 for the current player who does not get curse card
                printf("Warning: Not enough curse cards for all players. \n");
        }

        if (gameState->supplyCount[curse] != getExpectedCurseCardCount(gameState, currentPlayer, numCurseCards)) {
                printf("Error: Curse count supply was not correctly adjusted.  Expected %d remaining curse cards, not %d curse cards \n", getExpectedCurseCardCount(gameState, currentPlayer, numCurseCards), gameState->supplyCount[curse]);
        }
        int playerNumber = 0;
        for (; playerNumber < numPlayers; playerNumber++) {
                if (playerNumber != currentPlayer) {
                        if (initalDeckCount[playerNumber] <= 0) {
                                printf("Warning: Player %d had an empty deck and should not have been able to discard.  Current deckCount is now %d \n", playerNumber, gameState->deckCount[playerNumber]);
                        }
                }
                
        }

        
        if (numCurseCards < numPlayers - 1) {
                playerNumber = 0;
                for (; playerNumber < numPlayers; playerNumber++) {
                        if (playerNumber != currentPlayer) {
                                if (playerNumber <= numCurseCards) {
                                        //top deck card should be a curse card
                                        if (gameState->deck[playerNumber][gameState->deckCount[playerNumber] - 1] != curse) {
                                                printf("Error: Player %d did not receive a curse card \n", playerNumber);
                                        }
                                        if (initalDeckCount[playerNumber > 0 ]) {
                                                if (initalDeckCount[playerNumber] != gameState->deckCount[playerNumber]) {
                                                        printf("Error: DeckCount for player %d was incorrectly adjusted \n", playerNumber);
                                                }
                                        } else if (initalDeckCount[playerNumber] + 1 != gameState->deckCount[playerNumber]) {
                                                        printf("Error: DeckCount for player %d was incorrectly adjusted \n", playerNumber);
                                                }
                                        }

                                else {
                                        if (gameState->deck[playerNumber][gameState->deckCount[playerNumber] - 1] == curse) {
                                                printf("Error: Player %d received a curse card when none were available \n", playerNumber);
                                        }
                                        if (initalDeckCount[playerNumber > 0 ]) {
                                                if (initalDeckCount[playerNumber] - 1 != gameState->deckCount[playerNumber]) {
                                                        printf("Error: DeckCount for player %d was incorrectly adjusted \n", playerNumber);
                                                }
                                        }
                                }
                        }
                }

        } else {
                playerNumber = 0;
                for (; playerNumber < numPlayers; playerNumber++) {
                        if (playerNumber != currentPlayer) {
                                //top deck card should be a curse card
                                if (gameState->deck[playerNumber][gameState->deckCount[playerNumber] - 1] != curse) {
                                        printf("Error: Player %d did not receive a curse card \n", playerNumber);
                                }
                                if (initalDeckCount[playerNumber > 0 ]) {
                                        if (initalDeckCount[playerNumber] != gameState->deckCount[playerNumber]) {
                                                printf("Error: DeckCount for player %d was incorrectly adjusted \n", playerNumber);
                                        }
                                } else if (initalDeckCount[playerNumber] + 1 != gameState->deckCount[playerNumber]) {
                                                printf("Error: DeckCount for player %d was incorrectly adjusted \n", playerNumber);
                                }
                        
                        }
                }
        }
        

}

int getExpectedCurseCardCount(struct gameState* gameState, int currentPlayer, int numCurseCards) {
        int playerNumber = 0;
        int expectedCurseCount = numCurseCards;
        for (; playerNumber < gameState->numPlayers; playerNumber++) {
                if (playerNumber != currentPlayer) { //exclude current player since he/she would not have gotten a curse card
                        if (expectedCurseCount > 0) {
                                expectedCurseCount--;
                        }
                }
        }
        return expectedCurseCount;
}

int setCurrentPlayersHand(struct gameState* gameState, int currentPlayer) {
        
        int defaultCard = estate;
        int handPos = 0;
        int cardNumber = 0;
        gameState->handCount[currentPlayer] = handCount;

        gameState->hand[currentPlayer][cardNumber] = curse;
        cardNumber++;

        for (; cardNumber < handCount; cardNumber++) {
                gameState->hand[currentPlayer][cardNumber] = defaultCard;
        }

        return handPos;
}

int* initalizePlayerDecks(struct gameState* gameState) {
        int playerNumber = 0;
        int cardNumber = 0;
        int deckCount = 0;
        int maxDeckCount = 10;
        int defaultCard = estate;
        int* initalDeckCount = malloc(sizeof(int) * gameState->numPlayers);

        
        for ( ; playerNumber < gameState->numPlayers; playerNumber++) {
                deckCount = rand() % maxDeckCount;
                gameState->deckCount[playerNumber] = deckCount;
                initalDeckCount[playerNumber] = deckCount;


                for ( ; cardNumber < deckCount; cardNumber++) {
                        gameState->deck[playerNumber][cardNumber] = defaultCard;
                }
        }

        return initalDeckCount;
}